package com.tmanager.persistence.dao;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import com.google.inject.Singleton;
import com.tmanager.persistence.entity.User;


import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceException;
import javax.persistence.Query;
import javax.persistence.TypedQuery;


/**
 * @author Paul A. Shmarev
 */
@Singleton
class UserDAOImpl extends BaseDAO<User> implements UserDAO {

    public UserDAOImpl() {
        super(User.class);
    }

    @Override
    public User getUserByEmail(String email) {
        if (email == null) {
          	return null;
        }
        User user;
        TypedQuery<User> q = getEntManager().createNamedQuery(User.GET_BY_EMAIL, User.class);
        q.setParameter("email", email);
        try {
            user = q.getSingleResult();
        } catch (NoResultException e) {
            user = null;
        }
        return user;
    }
/*
    @Override
    public User authenticate(String email, String password) throws UserManagementException {
        User user = getUserByEmail(email);
        if (user != null && user.getPassword().equals(password)) {
            return user;
        }
        return null;
    }
    
    @Override
    public User getUserByUserId(Long UserId) throws UserManagementException {
        return getEntManager().find(User.class, UserId);
    }
    
    @Override
    public boolean hasRole(String roleName, String UserId) throws UserManagementException {
        if (UserId == null) {
            throw new UserManagementException("Cannot get role for null UserId");
        }
        if (roleName == null) {
            throw new UserManagementException("Cannot get role for null roleName");
        }

        Query query = getEntManager().createNamedQuery(UserRole.FIND_BY_USERID_AND_ROLENAME);
        query.setParameter("userId", UserId);
        query.setParameter("roleName", roleName);

        List results = query.getResultList();
        return results != null && (!results.isEmpty());
    }
    
    @Override
 // and to display the roles and permissions associated with each user
    public List<String> getRoles(Long userId) throws UserManagementException {
        if (userId == null) {
            throw new UserManagementException("Cannot get roles for null UserId");
        }

        List<String> roleStrings = new ArrayList<String>();

        Set<UserRole> roles = getUserByUserId(userId).getRoles();
        for (UserRole role : roles) {
            roleStrings.add(role.getRoleName());
        }
        return roleStrings;
    }
    
    
 // Grant and revoke roles because roles imply permissions
    // "is user in role" is provided by the container
    // role is granted to user but not save to database
    @Override
    public void grantRole(UserRoles roleName, User user) throws UserManagementException {
        if (roleName == null) {
            throw new UserManagementException("Cannot grant role with null roleName");
        }
        if (user == null) {
            throw new UserManagementException("Cannot grant role with null user");
        }

        UserRole role;
        try {
            role = getOrCreateRole(roleName);
            Set<UserRole> userRoles = user.getRoles();
            userRoles.add(role);
            user.setRoles(userRoles);
        } catch (Exception t) {
            throw new UserManagementException(t);
        }
    }
    
    @Transactional(rollbackOn = Exception.class)
    private UserRole createRole(UserRoles roleName){
    	 // create the role in database
            UserRole newRole = new UserRole();
            newRole.setRoleName(roleName.toString());
            getEntManager().persist(newRole);
            //getEntManager().flush();
            return newRole;
    }
    
    private UserRole getOrCreateRole(UserRoles roleName) throws PersistenceException {
        UserRole role = null;
        try {
            Query query = getEntManager().createNamedQuery(UserRole.FIND_BY_ROLENAME);
            query.setParameter("roleName", roleName.toString());
            role = (UserRole) query.getSingleResult();
        } catch (NoResultException nre) {
        	role = createRole(roleName);
        }

        // If role is null, try again (since it _should_ now exist in the DB).
       

        return role;
    }

    // role is revoked to user but not save to database
    public void revokeRole(String roleName, User user) throws UserManagementException {
        if (roleName == null) {
            throw new UserManagementException("Cannot revoke role with null roleName");
        }
        if (user == null) {
            throw new UserManagementException("Cannot revoke role with null user");
        }

        Query query = getEntManager().createNamedQuery(UserRole.FIND_BY_ROLENAME);
        query.setParameter("roleName", roleName);

        try {
            UserRole role = (UserRole) query.getSingleResult();
            Set<UserRole> userRoles = user.getRoles();
            userRoles.remove(role);
            user.setRoles(userRoles);
        } catch (NoResultException ex) {
            // no op
        }
    }

	@Override
	public List<User> getAll(int offset, int length) throws UserManagementException {
		List<User> users = new ArrayList<User>();

		Query query = getEntManager().createNamedQuery(User.GET_ALL);
		if (offset != 0) {
            query.setFirstResult(offset);
        }
        if (length != -1) {
            query.setMaxResults(length);
        }
		
        List results = query.getResultList();
        if (results != null) {
            for (Object obj : results) {
                users.add((User) obj);
            }
        }
        return users;
	}*/
}
